<template>
  <div class="dashboard-container" :style="obj">
    <!-- tools -->
    <div class="tools">
      <div class="board-tools-menu">
        <el-tooltip
          class="item"
          :enterable="false"
          :hide-after="1000"
          v-for="(item, index) in brushModelData"
          :key="index"
          effect="dark"
          :content="item.tip"
          placement="left"
        >
          <div class="itemtools" :class="{ active: isActive == index }">
            <i
              :class="item.icon"
              v-if="item.isSvg == 0"
              style="
                font-size: 18px;
                width: 38px;
                height: 38px;
                display: flex;
                justify-content: center;
                align-items: center;
              "
              @click.stop="setBrushModel(item.type)"
            />
            <i
              v-if="item.isSvg == 1"
              style="
                width: 38px;
                height: 38px;
                display: flex;
                justify-content: center;
                align-items: center;
              "
              @click.stop="setBrushModel(item.type)"
            >
              <svg-icon
                :icon-class="item.icon"
                style="font-size: 20px; color: #fff"
              />
            </i>
            <el-color-picker
              v-model="color"
              v-if="item.isSvg == 2"
              size="mini"
            />
          </div>
        </el-tooltip>
      </div>
    </div>
    <!-- canvas -->
    <div class="content" ref="canvasWrap">
      <canvas id="canvas"></canvas>
    </div>
  </div>
</template>

<script>
import { fabric } from "fabric"
import io from 'socket.io-client'
export default {
  data() {
    return {
      brushModelData: [
        { tip: '画笔', isSvg: 0, icon: 'el-icon-edit', type: 0 },
        { tip: '箭头', isSvg: 0, icon: 'el-icon-top-left', type: 1 },
        { tip: '直线', isSvg: 0, icon: 'el-icon-minus', type: 2 },
        { tip: '矩形', isSvg: 1, icon: 'ju', type: 3 },
        { tip: '文本', isSvg: 1, icon: 'text', type: 4 },
        { tip: '颜色', isSvg: 2, icon: '', type: 5 },
        { tip: '撤销', isSvg: 1, icon: 'che', type: 6 },
        { tip: '清空', isSvg: 1, icon: 'clear', type: 7 },
      ],
      isActive: 0,
      obj: { height: document.documentElement.clientHeight - 50 + 'px' },
      canvas: null,//画板初始值
      color: '#ff0000',
      width: 3,
      drawType: 'pen',
      mouseFrom: {},//起点的xy坐标
      mouseTo: {},//终点的xy轴坐标
      doDrawing: false,//是否开启绘制状态
      moveCount: 1,//绘制计数器
      drawingObject: null,//当前绘制对象
      textbox: null,
      socket: null
    }
  },
  methods: {
    // 初始化画板
    initDraw() {
      this.canvas = new fabric.Canvas('canvas', {
        isDrawingMode: true,//默认开启自由绘画模式
        selectable: false,     //设置是否可以选中拖动  fabric提供的
        selection: false,
        skipTargetFind: true, //画板元素不能被选中
      })
      this.canvas.backgroundColor = '#eee';
      this.canvas.freeDrawingBrush.color = this.color;
      this.canvas.freeDrawingBrush.width = this.width;
      this.handleResize()
      this.initEvent()
    },
    // 设置窗口大小
    handleResize() {
      let w = this.$refs.canvasWrap.offsetWidth
      let h = this.$refs.canvasWrap.offsetHeight
      this.canvas.setWidth(w)
      this.canvas.setHeight(h)
    },
    // 设置画板模式
    setBrushModel(type) {
      if (type != 5 && type != 6 && type != 7) {
        this.isActive = type
        this.canvas.isDrawingMode = false
      }
      if (this.textbox) { //退出文本模式，取消闪烁光标
        this.textbox.exitEditing();
        this.textbox = null;
      }
      switch (type) {
        case 0: //自由画笔模式
          this.canvas.isDrawingMode = true
          this.canvas.freeDrawingBrush.color = this.color;
          this.drawType = 'pen'
          break;
        case 1://箭头模式
          this.drawType = 'arrow'
          break;
        case 2://直线模式
          this.drawType = 'line'
          break;
        case 3://矩形模式
          this.drawType = 'rect'
          break;
        case 4://文本模式
          this.drawType = 'text'
          break;
        case 5://颜色

          break;
        case 6://撤销
          if (this.canvas._objects.length > 0) {
            this.canvas._objects.pop()
            this.canvas.renderAll();
          }
          break;
        case 7://清空
          this.canvas.clear();
          this.canvas.backgroundColor = '#eee';//设置背景颜色
          break;
        default:
          break;
      }
    },
    // 绘制箭头的方法
    drawArrow(fromX, fromY, toX, toY, theta, headlen) {
      theta = typeof theta != "undefined" ? theta : 30
      headlen = typeof theta != "undefined" ? headlen : 10
      // 计算各角度和对应的P2,P3坐标
      var angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
        angle1 = ((angle + theta) * Math.PI) / 180,
        angle2 = ((angle - theta) * Math.PI) / 180,
        topX = headlen * Math.cos(angle1),
        topY = headlen * Math.sin(angle1),
        botX = headlen * Math.cos(angle2),
        botY = headlen * Math.sin(angle2)
      var arrowX = fromX - topX,
        arrowY = fromY - topY
      var path = " M " + fromX + " " + fromY
      path += " L " + toX + " " + toY
      arrowX = toX + topX
      arrowY = toY + topY
      path += " M " + arrowX + " " + arrowY
      path += " L " + toX + " " + toY
      arrowX = toX + botX
      arrowY = toY + botY
      path += " L " + arrowX + " " + arrowY
      return path
    },
    // 监听画板鼠标按下，移动，抬起事件
    initEvent() {
      this.canvas.on("mouse:down", (options) => {
        this.mouseFrom.x = options.e.offsetX;//记录开始的坐标x点
        this.mouseFrom.y = options.e.offsetY;//记录开始的坐标y点
        this.doDrawing = true //是否是绘制状态
      })
      this.canvas.on("mouse:move", (options) => {
        if (this.moveCount % 2 && !this.doDrawing) {
          //减少绘制频率
          return
        }
        this.moveCount++
        this.mouseTo.x = options.e.offsetX;
        this.mouseTo.y = options.e.offsetY;
        this.drawing() //执行绘制方法
      })
      this.canvas.on("mouse:up", (options) => {
        this.moveCount = 1
        this.doDrawing = false
        this.mouseTo.x = options.e.offsetX;
        this.mouseTo.y = options.e.offsetY;
        this.drawingObject = null;
        this.mouseFrom = {};
        this.mouseTo = {};
        this.socket.emit("startConnect", this.canvas.toJSON())
      })
    },
    // 绘制方法
    drawing() {
      if (this.drawingObject) {
        this.canvas.remove(this.drawingObject)
      }
      let canvasObject = null
      switch (this.drawType) {
        case "pen": //drawType为‘pen’时，开启自由画笔模式
          this.canvas.isDrawingMode = true
          this.canvas.freeDrawingBrush.color = this.color;

          break;
        case "arrow": //箭头
          canvasObject = new fabric.Path(
            this.drawArrow(this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this.mouseTo.y, 30, 20), {
            stroke: this.color,
            fill: "rgba(255,255,255,0)",
            strokeWidth: this.width,
          }
          )
          break;
        case "line": //箭头
          canvasObject = new fabric.Line(
            [this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this.mouseTo.y], {
            stroke: this.color,
            strokeWidth: this.width,
          }
          )
          break;
        case "rect": //矩形
          let left = this.mouseFrom.x;
          let top = this.mouseFrom.y;
          let width = this.mouseTo.x - this.mouseFrom.x;
          let height = this.mouseTo.y - this.mouseFrom.y;
          canvasObject = new fabric.Rect({
            left: left,
            top: top,
            width: width,
            height: height,
            stroke: this.color,
            fill: "rgba(255, 255, 255, 0)",
            strokeWidth: this.width
          });
          break;
        case "text":
          this.textbox = new fabric.Textbox(" ", {
            left: this.mouseFrom.x,
            top: this.mouseFrom.y,
            width: 150,
            fontSize: 18,
            borderColor: "#2c2c2c",
            fill: this.color,
            hasControls: false,
            selectable: false,//不可被选中
          })
          this.canvas.add(this.textbox)
          this.textbox.enterEditing()
          this.textbox.hiddenTextarea.focus()
          break;
        default:
          break;
      }
      if (canvasObject) {
        this.canvas.add(canvasObject)
        this.drawingObject = canvasObject
      }
    },
    // 初始化WebSocket
    initWebSocket() {
      this.socket = null
      this.socket = io.connect('http://localhost:3000', {
        transports: ['websocket'],
      })
      this.socket.on('connect', () => {
        console.log('链接成功');
      })
      this.socket.on('init', data => {
        console.log(data);
      })
      this.socket.on('drawCanvas', data => {
        this.canvas.loadFromJSON(data)
      })
    }
  },
  mounted() {
    window.onresize = () => {
      return (() => {
        this.obj.height = (document.documentElement.clientHeight
          || document.body.clientHeight) - 50 + 'px'
      })()
    }
    window.addEventListener('resize', this.handleResize, false);
    this.initDraw()
    this.initWebSocket()
  }
}
</script>

<style lang="scss" scoped>
.dashboard-container {
  width: 100%;
  height: 100%;
  background: red;
  .content {
    width: 100%;
    height: 100%;
  }
  .tools {
    position: absolute;
    right: 12px;
    top: 60px;
    width: 55px;
    z-index: 2;
    .board-tools-menu {
      padding: 2px 0;
      display: flex;
      flex-direction: column;
      width: 46px;
      min-height: 46px;
      border-radius: 6px;
      background-color: rgba(51, 51, 51, 0.4);
      justify-content: center;
      align-items: center;
      pointer-events: all;
      .itemtools {
        width: 38px;
        height: 38px;
        background: #565656;
        cursor: pointer;
        display: flex;
        justify-content: center;
        align-items: center;
        border-radius: 4px;
        color: #fff;
        margin-bottom: 6px;
        &:first-child {
          margin-top: 3px;
        }
        &:last-child {
          margin-bottom: 3px;
        }
        &:hover {
          background: #141414;
          border: 1px solid #eee;
        }
        ::v-deep .el-color-picker__trigger {
          border: none;
        }
      }
      .active {
        background: #141414;
        border: 1px solid #eee;
      }
    }
  }
}
</style>